Skip to content

Conversation

asgeija
Copy link
Member

@asgeija asgeija commented Nov 5, 2026

What

Parent issue #142: makes the report a sighting form clearer and easier to use.

  • Clearer form layout (c64f6ac)
  • Dates in the future or before 1900 are caught in the browser: on blur and on submit. The server still validates and stays the final check.
  • Duration is entered as a number and a unit (seconds, minutes, hours) and converted to seconds before submitting. The API and database are unchanged.
  • SubmitSightingPage.tsx is split into smaller parts: form rules in utils/sighting-form.ts, state and submit in a useSightingForm hook, plus FormField and LocationSection components. Behavior is unchanged.
  • Place search: a keyboard-accessible combobox finds a location by name. Choosing a result sets the marker, moves the map and fills in the location fields. Screen readers hear searching, result count, no results, errors and the chosen place.
  • An error summary above the submit button lists each invalid field with its error, as links that move focus to the field. Field-level errors and the focus on the first invalid field are unchanged.

Nominatim

The place search follows Nominatim's usage policy: it runs only on Enter or the button, never while typing. Search and pin lookups share one module that keeps requests at least a second apart, and search answers are cached for the visit. Described in docs/sustainability.md.

Testing

  • npm run lint, npm run test (unit) and npm run test:e2e pass.
  • New unit tests for validation, unit conversion, place search and the error summary.
  • New e2e tests for finding a place with the keyboard alone and for following the error summary links.
  • Please check the layout at desktop and mobile widths, in light and dark mode as well.

Notes for review

  • The 1900 and one-year limits are copied from the backend. The server checks them again, but the two copies have to be kept in sync by hand.
  • The date picker has no max attribute. Chromium moves from the year to the hour on its own once a max is set, which breaks keyboard entry. The check on blur gives the same feedback.
  • A server error on the State field now shows under it. Before, it was mapped but not displayed.

AI usage

Claude Code helped refactoring the code and write/change tests. I reviewed the output and tested it.

Closes #142
Closes #153
Closes #154
Closes #167
Closes #175
Closes #176

Group location fields with the map and add a mobile map/manual toggle.
Update keyboard-flow and validation tests for the new form order.

Closes #142
The server rejects sightings dated in the future or before 1900, but
the report form only showed that after a failed request.

Check the date in the browser when the user leaves the field and on
submit, and show the message under the field. The server still
validates and stays the final check.

Update the e2e server-error test to use a mocked error, since the
client now catches the dates it used. Add unit and e2e tests for the
new checks.

AI usage: Test added using Claude Code.

Closes #153
The report form asked for the duration in seconds, so a 15 minute
sighting had to be entered as 900.

Add a unit select (seconds, minutes or hours) next to the number
input, defaulting to minutes. The form converts the value to seconds
before submitting, so the API and database stay unchanged. Decimals
such as 1.5 hours are allowed.

Update the tests for the new label and add a test for the unit
conversion.

AI usage: Claude code was used to update the test.

Closes #154
Move validation and duration conversion to utils/sighting-form.ts,
form state and submit handling to a useSightingForm hook, and the
shared field markup and location section to their own components.
The page now only lays out the form.

Behavior is unchanged, except that a server error on the State field
now shows under it.

AI usage: Claude Code was used to refactor the code.

Closes #167
Let users find a location by name with a keyboard-accessible combobox.
Choosing a result sets the marker and fills in the location fields.

Search only runs on Enter or the button, and shares one request
spacing and cache with the pin lookups, to follow Nominatim's policy.

AI usage: Claude Code used to modify test

Closes #175
After a failed submit, list each invalid field with its error above
the submit button. Each item is a link that moves focus to its field.
The summary updates as fields are fixed. Field-level errors and the
focus on the first invalid field are unchanged.

Closes #176
@asgeija asgeija added bug Something isn't working feat New feature frontend accessibility labels Nov 5, 2026
@asgeija asgeija added this to the Partial submission 4 milestone Nov 5, 2026
@asgeija asgeija requested a review from a team as a code owner November 5, 2026 10:55
@asgeija asgeija linked an issue Nov 5, 2026 that may be closed by this pull request
5 tasks
Copy link
Member

@thortve thortve left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When opening the submit form without a connection to the database, the shape drop-down menu defaults to a pre-made list of shapes. It also adds a label under the shape menu which pushes the shape menu up and creates this weird asymmetry (see figure).

image

@thortve thortve self-requested a review November 5, 2026 11:25
Copy link
Member

@thortve thortve left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Now it looks great. Ready for prod.

image

@asgeija asgeija merged commit 1b74fc1 into main Nov 5, 2026
2 checks passed
@asgeija asgeija deleted the 142-iteration-4-make-the-submit-forms-layout-clearer branch November 5, 2026 11:29
Sign in to join this conversation on GitHub.
Labels
accessibility bug Something isn't working feat New feature frontend
Projects
None yet
2 participants